/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#ifndef OBS_PLUGIN_UTILITIES_H
#define OBS_PLUGIN_UTILITIES_H

#include <string>
#include <set>
#include <shared_mutex>
#include <ctime>
#include <fstream>
#ifndef WIN32
#include <libgen.h>
#endif
#include <boost/asio.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/functional/hash.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include "define/Types.h"
#include "log/Log.h"
#include "device_access/dorado/DoradoBlock.h"

namespace OBSPlugin {
    constexpr uint32_t NUMBER1 = 1;
    bool CheckDeviceNetworkConnect(const std::string &managerIps);
    std::string FormatTimeToStrBySetting(time_t timeInSeconds, const std::string& timeFormat);
    std::string FormatTimeToStr(time_t timeInSeconds);
    void LogCmdExecuteError(int retCode, const std::vector<std::string> &output,
                            const std::vector<std::string> &errOutput);
    int RunShellCmd(const std::string& cmd, const std::vector<std::string>& paramList);
    int RunShellCmd(const std::string& cmd, const std::vector<std::string>& paramList,
        std::vector<std::string>& output);

    time_t GetCurrentTimeInSeconds();
    time_t GetCurrentTimeInSecondsString(std::string &dateAndTimeString);
    std::string ConvertToReadableTime(time_t time);
    std::string GetPathName(const std::string &filePath);
    std::string GetFileName(const std::string &filePath);
    bool WriteFile(const std::string &filePath, std::vector<std::string>& fileContent);
    bool ReadFile(const std::string &filePath, std::vector<std::string>& fileContent);
    bool CreateDirectory(const std::string& path);
    bool RecurseCreateDirectory(const std::string& path);
    bool Remove(std::string path);
    bool IsPathExists(const std::string &path);
    bool Rename(std::string srcPath, std::string dstPath);

    bool IsDirExist(const std::string& pathName);
    bool IsFileExist(const std::string& fileName);
    bool IsPigzExist();
    bool CopyFile(std::string srcfile, std::string dstfile);
    bool RemoveFile(const std::string& path);
    bool GetFileListInDirectory(std::string dir, std::vector<std::string>& fileList);
    bool GetDirListInDirectory(std::string dir, std::vector<std::string>& fileList, bool skipSnapshot = false);
    std::string GetParentDirName(const std::string& dir);

    size_t GenerateHash(std::string jobId);
    std::string FormatCapacity(uint64_t capacity);
    std::string FloatToString(const float &val, const uint8_t &precisson = NUMBER1);
    // remove \n \t in str
    void StripWhiteSpace(std::string& str);
    std::string ReverseSlash(const std::string& path);
    std::string PathJoin(std::initializer_list<std::string> paths);
    inline void RemoveDoubleSlash(std::string &str);
    inline void RemoveDoubleBackSlash(std::string &str);
    std::string LowerCase(const std::string& path);
    std::string FormatSpeed(uint64_t speed);
    std::string GetDeployType();
    bool GetInnerPodIp(std::string& podIp);
    bool OperateIpsRule(const std::vector<std::string>& ipList, const Module::IpRuleOperation& operation);
    std::string Base64Decode(const std::string &in);
    bool Base64Decryption(std::string& encryptedkey, std::string &plainKey);

#ifndef WIN32
    std::string GetRealPath(const std::string& path);
    std::string GetDirName(const std::string& path);
    bool IsDir(const std::string& path);
#endif
    std::string PrepareUnZipCommand(const std::string &workDir, const std::string &dcache,
        const std::string &fcache, const std::string &meta, const std::string &xmeta);
    int CopyPreviousMetaFile(
        const std::string& prefixSubStr, const std::string& metaPath, bool& isUnzipping, bool& isSuccess);
    bool CheckUnzipMetafileSucceed(const std::string& execCmd, const std::string& workDir);
    bool CheckMetafileExists(const std::string& workDir);
    std::string StandardPath(const std::string& path);
    void CheckAndDeleteFiles(const std::string& fileName);
    template<class ... T>
    std::string PathJoin(T&&... paths)
    {
        return PathJoin({ paths... });
    }

    void SetPluginConfigInt(const std::string& keyName, int minValue, int maxValue, int defValue);
    void SetPluginConfigString(const std::string& keyName, const std::string& defaultValue);

    bool CheckIsValidIP(const std::string& ip);
    bool CheckIsValidIPv6(const std::string& ip);
    std::string ParseDomain2IP(const std::string &domain);
    std::string GetIPFromDomain(const std::string &domain);

    class PluginUtilities {
    public:
        static bool VectorStrEqual(std::vector<std::string> a, std::vector<std::string> b)
        {
            if (a.empty() && b.empty()) {
                return true;
            }
            if (a.size() != b.size()) {
                return false;
            }
            sort(a.begin(), a.end());
            sort(b.begin(), b.end());
            for (std::size_t i = 0; i < a.size(); ++i) {
                if (a[i] != b[i]) {
                    return false;
                }
            }
            return true;
        }
    };
}
#endif  // OBS_PLUGIN_UTILITIES_H